今天是最後一天!我們來學一下如何使用進階的路徑設定,也就是怎麼在路徑上面使用正規表達式。
我們前面設定路徑的時候,都是用 path
,來達成我們想要設定的路徑,但是有時候在設定路徑時,我們設定的規則不會這麼簡單,有時候會加上一些限定的條件,讓該路徑被使用時,是有 規則/限制
的,那要怎麼達成這個目的呢?這邊就可以利用 正規表達式 regular expression
,來達成我們的目標。
PS. 如果聽不懂沒關係,我們來看下面的實際案例
我們用這次使用到的 產品 Product
當作範例,首先我們看下面這兩行程式,這兩行程式的意思是一樣的:
# 原先的路徑設定
path("product/<int:pk>", views.ProductDetailView.as_view(), name="product-detail"),
# 使用正規表達式的路徑設定
re_path(r'^product/(?P<pk>\d+)$', views.ProductDetailView.as_view(), name="product-detail"),
原先我們在設定 product-detail
路徑的時候,是用 path
來設定,那一段最後對應的 url
是這樣, http://127.0.0.1:8000/online/product/2
撇除前段路徑 http://127.0.0.1:8000/online/
不看,真正用到的是這一段 product/2
,這邊也很容易了解,這一段是對應上 product/<int:pk>
的,這邊的 <int:pk>
就是對應上物件的 primary key
。
今天當我們換使用 re_path
呢?為什麼會跟 path
的意義一樣呢?我們實際換一次就知道了,下面是產品原本的路徑設定:
# store/online/urls.py
urlpatterns += [
path("products/", views.ProductListView.as_view(), name='product-list'),
path("product/create/", views.ProductCreate.as_view(), name='product-create'),
path("product/<int:pk>", views.ProductDetailView.as_view(), name="product-detail"),
path("product/<int:pk>/update/", views.ProductUpdate.as_view(), name="product-update"),
path("product/<int:pk>/delete/", views.ProductDelete.as_view(), name="product-delete"),
]
改成下面這樣:
# store/online/urls.py
from django.urls import path, re_path
urlpatterns += [
path("products/", views.ProductListView.as_view(), name='product-list'),
path("product/create/", views.ProductCreate.as_view(), name='product-create'),
# 修改這一段
re_path(r'^product/(?P<pk>\d+)$', views.ProductDetailView.as_view(), name="product-detail"),
# 修改這一段
path("product/<int:pk>/update/", views.ProductUpdate.as_view(), name="product-update"),
path("product/<int:pk>/delete/", views.ProductDelete.as_view(), name="product-delete"),
]
這樣修改好後,我們到瀏覽器輸入以下網址 http://127.0.0.1:8000/online/product/1
(要確保你有商品喔),應該可看到以下畫面:
發現這樣改後,我們的 product-detail
頁面也可以正常運行,代表這兩段式相同的意思,那接下來我們就來解釋 re_path
這一段是什麼意思拉~
要釐清這一段的意思前,我們要先了解關於 正規表達式 regular expression
的各種符號意義,因此來看以下的圖表,以下圖表是從 https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Generic_views
MDN Django 教學找到的,原本是英文,因此我這邊只是單純把它翻成中文~
符號 | 意義 |
---|---|
^ |
匹配文字的開頭 |
$ |
匹配文字的結尾 |
\d |
匹配數字(0, 1, 2....9) |
\w |
匹配單字字符,例如 字母表中的任何大寫或小寫字元、數字或底線字元 (_) |
+ |
匹配一個或多個前面的字元。 例如,要符合一位或多位數字,您可以使用 \d+ 。 要匹配一個或多個“a” 字符,您可以使用 a+ |
* |
匹配零個前面的字元。 例如,如果不匹配任何內容或一個單詞,您可以使用 \w |
() |
捕捉括號內的模式(pattern)部分。 任何捕獲的值都將作為未命名參數傳遞到視圖(如果捕獲了多個模式(pattern),則將按照捕獲的順序提供關聯參數) |
(?P<name>...) |
將模式(pattern)捕獲為命名變數(在本例中為'name')。 捕獲的值將傳遞到具有指定名稱的views。 因此,您的 views 必須宣告一個同名的參數! |
[] |
與中括號中的任一個字元相符。 例如,[abc] 將符合'a'、'b'或'c'。 [-\w]將匹配“-”字元或任何單字字元。 |
看完符號定義表後,我們來拆解剛剛那一段的 re_path
- (r'^product/(?P<pk>\d+)$')
:
re_path(r'^product/(?P<pk>\d+)$', views.ProductDetailView.as_view(), name="product-detail"),
^product/
: 代表整段連結 開頭
為 product/
(?P<pk>\d+)
: 代表會捕捉所有的數字,並且把這些數字當作 pk 變數
,傳到 views 那邊使用$
: 最後結尾例如: 如果今天我的連結是這樣: http://127.0.0.1:8000/online/product/1222
,他會傳對應到 /product/1222
,並且傳遞變數 pk='1222'
到指定的 view (這邊的 view 就是ProductDetailView)
re_path(r'^product/(\d+)$')
上面的範例跟 (r'^product/(?P<pk>\d+)$')
有點像,不過差異就在一個有指定變數名稱(pk),一個沒有,所以今天假設 re_path
是這樣寫 (r'^product/(\d+)$')
,當我們連結輸入 http://127.0.0.1:8000/online/product/1222
時,會朝 views 送一個沒有命名的變數,且該值為 1222
。
re_path(r'^product/(?P<stub>[-\w]+)$')
這個跟剛剛比起來稍稍不太一樣,讓我們來解釋一下吧~
^product/
: 代表整段連結 開頭
為 product/
(?P<stub>[-\w]+)
: 這一段為捕捉 數個 '-' 和 \w(文字)
,抓到後一起把他們當作變數(stub),傳到 views 那邊使用$
: 最後結尾此案例是一種設定 url
路徑很典型的模式,因為 stub
是一種基於 文字版的primary key
,聽不懂這一句話沒關係,我們直接看下面的例子。
以往我們看個別產品的詳細資訊,路徑都是這樣 http://127.0.0.1:8000/online/product/1222
,但是假設今天我不想用數字代表這個產品,我想要用英文字,像這樣: http://127.0.0.1:8000/online/product/lufy-comic-books
,像這樣用英文字,就可以知道這個產品代表的意義,如果今天只是單純用數字就看不出來這個產品是什麼。
因此如果想要用英文取代數字的話,就可以把路徑換成這樣:re_path(r'^product/(?P<stub>[-\w]+)$')
終於完賽拉~~~~今天就是第 30 天,也是我第一次參加鐵人賽的最後一天,也因為這一次的經歷,希望讓跟我一樣的人,從原本寫 ROR 的人,跳到 Django 的學習成本可以不要這麼高!
以下附上我在寫這30天文章時參考網站:
Django MDN: https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Introduction
Django 官網: https://www.djangoproject.com/
pyenv 安裝、指令: https://ephrain.net/python-%E4%BD%BF%E7%94%A8-pyenv-%E5%9C%A8-mac-%E4%B8%8A%E5%AE%89%E8%A3%9D%E5%B7%B2%E7%B6%93%E6%B6%88%E5%A4%B1%E7%9A%84-python-2-%E7%89%88%E6%9C%AC/